package il.ac.bgu.cs.heuristics.ui;

import static il.ac.bgu.cs.heuristics.utils.MathUtils.average;
import il.ac.bgu.cs.heuristics.ui.MainWindow.AddProblemActionListener;
import il.ac.bgu.cs.heuristics.utils.Pair;
import il.ac.bgu.cs.heuristics.utils.Tuple;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * 
 * @author Ronen Pinko
 * 
 */
@SuppressWarnings("serial")
public class AddProblemDialog extends JDialog{
	private final static String DIALOG_TITLE = "Add Problem";
	private final static Pair<Integer> DIALOG_DIMENSIONS = new Pair<Integer>(
	        600, 220);
	private final static int GENERAL_BUTTON_HEIGHT = 20;
	private final static int GENERAL_BUTTON_WIDTH = 100;
	private File domain;
	private File problem;
	private File contradictions;
	private final AddProblemActionListener targetListener;
	private JLabel problemFileSelectionLabel;
	private JLabel domainFileSelectionLabel;
	private JLabel contradictionFileSelectionLabel;

	private int componentCount = 0;
	private final static int FILE_PATH_LABEL_X = MainWindow.COMPONENT_MINIMUM_DISTANCE
	        + GENERAL_BUTTON_WIDTH + MainWindow.COMPONENT_MINIMUM_DISTANCE;
	private final static int FILE_PATH_LABEL_WIDTH = DIALOG_DIMENSIONS
	        .getFirst()
	        - (MainWindow.COMPONENT_MINIMUM_DISTANCE + GENERAL_BUTTON_WIDTH + MainWindow.COMPONENT_MINIMUM_DISTANCE)
	        - MainWindow.WINDOW_WIDTH_OVERHEAD
	        - MainWindow.COMPONENT_MINIMUM_DISTANCE;

	private int getNextComponentY() {
		final int y = GENERAL_BUTTON_HEIGHT * componentCount
		        + (componentCount + 1) * MainWindow.COMPONENT_MINIMUM_DISTANCE;
		componentCount++;
		return y;
	}

	public AddProblemDialog(AddProblemActionListener targetListener) {
		super();
		this.targetListener = targetListener;
		setModalityType(ModalityType.APPLICATION_MODAL);

		final int dialogWidth = DIALOG_DIMENSIONS.getFirst();
		final int dialogHeight = DIALOG_DIMENSIONS.getSecond();
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		setLocationRelativeTo(null);
		setSize(dialogWidth, dialogHeight);
		final Dimension size = getToolkit().getScreenSize();
		setLocation(average(size.width, -dialogWidth), average(size.height,
		        -dialogHeight));

		setTitle(DIALOG_TITLE);

		final JPanel panel = new JPanel();
		getContentPane().add(panel);

		panel.setLayout(null);

		createUserInstruction(panel);
		createAddDomainButton(panel);
		createAddProblemUi(panel);
		createAddContradictionButton(panel);
		createOkButton(panel);

	}

	private void createUserInstruction(final JPanel panel) {
		final JLabel instruction = new JLabel(
		        "Please load PDDL domain, problem, types definition and contradictions files");
		instruction.setBounds(MainWindow.COMPONENT_MINIMUM_DISTANCE,
		        getNextComponentY(), 500, GENERAL_BUTTON_HEIGHT);

		panel.add(instruction);
	}

	private void createOkButton(final JPanel panel) {
		final int dialogWidth = DIALOG_DIMENSIONS.getFirst();
		final JButton okButton = new JButton("OK");
		final int x = dialogWidth - MainWindow.WINDOW_WIDTH_OVERHEAD
		        - GENERAL_BUTTON_WIDTH - MainWindow.COMPONENT_MINIMUM_DISTANCE;
		final int y = getNextComponentY();
		okButton.setBounds(x, y, GENERAL_BUTTON_WIDTH, GENERAL_BUTTON_HEIGHT);
		okButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				if (domain == null) {
					UiUtils.showErrorDialog("Domain file must be selected");
				} else if (problem == null) {
					UiUtils.showErrorDialog("Problem file must be selected");
				} else if (contradictions == null) {
					UiUtils
					        .showErrorDialog("Contradictions file must be selected");
				} else {
					targetListener.onProblemInputReceived(new Tuple<File>(
					        domain, problem, contradictions));
					setVisible(false);
				}

			}
		});
		panel.add(okButton);
	}

	private void createAddProblemUi(final JPanel panel) {
		final int buttonY = getNextComponentY();
		final JButton addProblemFileButton = new JButton("Problem ...");
		addProblemFileButton.setBounds(MainWindow.COMPONENT_MINIMUM_DISTANCE,
		        buttonY, GENERAL_BUTTON_WIDTH, GENERAL_BUTTON_HEIGHT);
		addProblemFileButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				problem = chooseFile(panel);
				if (problem != null) {
					problemFileSelectionLabel
					        .setText(problem.getAbsolutePath());
				}
			}
		});

		problemFileSelectionLabel = new JLabel();
		problemFileSelectionLabel.setBounds(FILE_PATH_LABEL_X, buttonY,
		        FILE_PATH_LABEL_WIDTH, GENERAL_BUTTON_HEIGHT);
		problemFileSelectionLabel.setBorder(BorderFactory
		        .createLineBorder(Color.BLACK));
		panel.add(addProblemFileButton);
		panel.add(problemFileSelectionLabel);
	}

	private void createAddContradictionButton(final JPanel panel) {
		final int buttonY = getNextComponentY();
		final JButton addProblemFileButton = new JButton("Cont ...");
		addProblemFileButton.setBounds(MainWindow.COMPONENT_MINIMUM_DISTANCE,
		        buttonY, GENERAL_BUTTON_WIDTH, GENERAL_BUTTON_HEIGHT);
		addProblemFileButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				contradictions = chooseFile(panel);
				if (contradictions != null) {
					contradictionFileSelectionLabel.setText(contradictions
					        .getAbsolutePath());
				}
			}
		});

		contradictionFileSelectionLabel = new JLabel();
		contradictionFileSelectionLabel.setBounds(FILE_PATH_LABEL_X, buttonY,
		        FILE_PATH_LABEL_WIDTH, GENERAL_BUTTON_HEIGHT);
		contradictionFileSelectionLabel.setBorder(BorderFactory
		        .createLineBorder(Color.BLACK));
		panel.add(addProblemFileButton);
		panel.add(contradictionFileSelectionLabel);
	}

	private void createAddDomainButton(final JPanel panel) {
		final JButton addDomainFileButton = new JButton("Domain ...");
		final int buttonY = getNextComponentY();
		addDomainFileButton.setBounds(MainWindow.COMPONENT_MINIMUM_DISTANCE,
		        buttonY, GENERAL_BUTTON_WIDTH, GENERAL_BUTTON_HEIGHT);
		addDomainFileButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				domain = chooseFile(panel);
				if (domain != null) {
					domainFileSelectionLabel.setText(domain.getAbsolutePath());
				}
			}

		});
		domainFileSelectionLabel = new JLabel();
		domainFileSelectionLabel.setBounds(FILE_PATH_LABEL_X, buttonY,
		        FILE_PATH_LABEL_WIDTH, GENERAL_BUTTON_HEIGHT);
		domainFileSelectionLabel.setBorder(BorderFactory
		        .createLineBorder(Color.BLACK));
		panel.add(addDomainFileButton);
		panel.add(domainFileSelectionLabel);
	}

	/**
	 * may return {@code null}.
	 */
	private File chooseFile(final JPanel panel) {
		final JFileChooser fileopen = new JFileChooser();
		final FileFilter filter = new FileNameExtensionFilter(
		        "PDDL problem files", "pddl", "txt");
		fileopen.addChoosableFileFilter(filter);

		final int ret = fileopen.showDialog(panel, "OK");
		return ret == JFileChooser.APPROVE_OPTION ? fileopen.getSelectedFile()
		        : null;
	}

}
